package cn.wolfcode.business.service.impl;

import cn.wolfcode.business.domain.BusBpmnInfo;
import cn.wolfcode.business.domain.BusCarPackageAudit;
import cn.wolfcode.business.domain.BusServiceItem;
import cn.wolfcode.business.mapper.BusServiceItemMapper;
import cn.wolfcode.business.service.IBusBpmnInfoService;
import cn.wolfcode.business.service.IBusCarPackageAuditService;
import cn.wolfcode.business.service.IBusServiceItemService;
import cn.wolfcode.business.vo.AuditInfoVO;
import cn.wolfcode.business.vo.AuditVO;
import cn.wolfcode.common.core.domain.entity.SysUser;
import cn.wolfcode.common.utils.DateUtils;
import cn.wolfcode.common.utils.SecurityUtils;
import cn.wolfcode.system.service.ISysConfigService;
import cn.wolfcode.system.service.ISysUserService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Service
public class IBusServiceItemServiceImpl implements IBusServiceItemService {
    @Autowired
    private BusServiceItemMapper busServiceItemMapper;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private ISysConfigService sysConfigService;
    @Autowired
    private IBusCarPackageAuditService busCarPackageAuditService;
    @Autowired
    private IBusBpmnInfoService busBpmnInfoService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;

    @Override
    public BusServiceItem selectBusServiceItemById(Long id) {
        return busServiceItemMapper.selectBusServiceItemById(id);
    }

    @Override
    public List<BusServiceItem> selectBusServiceItemList(BusServiceItem busServiceItem) {
        return busServiceItemMapper.selectBusServiceItemList(busServiceItem);
    }

    @Override
    //新增功能 返回受影响的行数
    public int insertBusServiceItem(BusServiceItem busServiceItem) {
        //参数合理化验证
        if (busServiceItem == null) {
            throw new RuntimeException("非法参数");
        }

        //前端校验过的后端都要校验一次
        if (
                busServiceItem.getName() == null ||
                        busServiceItem.getOriginalPrice() == null ||
                        busServiceItem.getDiscountPrice() == null ||
                        busServiceItem.getCarPackage() == null ||
                        busServiceItem.getServiceCatalog() == null
        ) {
            throw new RuntimeException("非法参数");
        }

        //折扣价合化校验
        //前面大返回正数，后面大返回负数，一样大返回0
        if (!(busServiceItem.getDiscountPrice().compareTo(new BigDecimal(0)) >= 0 && busServiceItem.getDiscountPrice().compareTo(busServiceItem.getOriginalPrice()) <= 0)) {
            throw new RuntimeException("折扣价必须大于0且不能大于原始价");
        }

        //在新增中存在一个是否套餐，状态不同
        if (BusServiceItem.CARPACKAGE_NO.equals(busServiceItem.getCarPackage())) {
            //若是非套餐 则无需审核
            busServiceItem.setAuditStatus(BusServiceItem.AUDITSTATUS_NO_REQUIRED);
        } else {
            //若是套餐，设置为初始化
            busServiceItem.setAuditStatus(BusServiceItem.AUDITSTATUS_INIT);
        }

        //安全性设置 前端传递的数据必须重新设置默认值
        //需要将新增的数据设置为默认下架状态
        busServiceItem.setSaleStatus(BusServiceItem.SALESTATUS_OFF);
        busServiceItem.setCreateTime(DateUtils.getNowDate());

        return busServiceItemMapper.insertBusServiceItem(busServiceItem);
    }

    @Override
    //编辑功能 返回受影响的行数
    public int updateBusServiceItem(BusServiceItem busServiceItem) {
        //参数合理化验证
        if (busServiceItem == null) {
            throw new RuntimeException("非法参数");
        }

        //前端校验过的后端都要校验一次
        if (
                busServiceItem.getName() == null ||
                        busServiceItem.getOriginalPrice() == null ||
                        busServiceItem.getDiscountPrice() == null ||
                        busServiceItem.getCarPackage() == null ||
                        busServiceItem.getServiceCatalog() == null
        ) {
            throw new RuntimeException("非法参数");
        }

        //折扣价合化校验
        //前面大返回正数，后面大返回负数，一样大返回0
        if (!(busServiceItem.getDiscountPrice().compareTo(new BigDecimal(0)) >= 0 && busServiceItem.getDiscountPrice().compareTo(busServiceItem.getOriginalPrice()) <= 0)) {
            throw new RuntimeException("折扣价必须大于0且不能大于原始价");
        }

        //安全性考虑，看前端传过来的对象在数据库中是否存在
        BusServiceItem busServiceItem1 = this.selectBusServiceItemById(busServiceItem.getId());
        if (busServiceItem1 == null) {
            throw new RuntimeException("非法参数");
        }

        //安全性考虑，防止前端页面篡改css样式使得编辑按钮能够暂时使用，必须处于下架状态可以进行编辑
        if (BusServiceItem.SALESTATUS_ON.equals(busServiceItem.getSaleStatus())) {
            throw new RuntimeException("上架中的服务项禁止修改");
        }

        //是否套餐禁止修改
        if (!busServiceItem1.getCarPackage().equals(busServiceItem.getCarPackage())) {
            throw new RuntimeException("非法参数");
        }

        //商品处于下架状态 且非套餐，可以直接修改
        //商品处于下架状态，且是套餐，若是审核中不能修改
        if (BusServiceItem.CARPACKAGE_YES.equals(busServiceItem1.getCarPackage()) && BusServiceItem.AUDITSTATUS_AUDITING.equals(busServiceItem1.getAuditStatus())) {
            throw new RuntimeException("审批中的服务项禁止修改");
        }

        //套餐状态若是初始化可以直接修改
        //套餐状态若是审核通过或是审核拒绝，可以修改，但是修改后需要将审核状态设置为初始化
        if (BusServiceItem.CARPACKAGE_YES.equals(busServiceItem1.getCarPackage()) && (BusServiceItem.AUDITSTATUS_APPROVED.equals(busServiceItem1.getAuditStatus())) || BusServiceItem.AUDITSTATUS_REPLY.equals(busServiceItem1.getAuditStatus())) {
            //设置为初始化
            busServiceItem.setAuditStatus(BusServiceItem.AUDITSTATUS_INIT);
        }

        //安全性考虑，再次都设置上下架状态
        busServiceItem.setSaleStatus(BusServiceItem.SALESTATUS_OFF);
        return busServiceItemMapper.updateBusServiceItem(busServiceItem);
    }

    @Override
    //删除功能 返回受影响的行数
    public int deleteBusServiceById(Long id) {
        if (id == null) {
            throw new RuntimeException("非法参数");
        }
        BusServiceItem busServiceItem = this.selectBusServiceItemById(id);
        if (busServiceItem == null) {
            throw new RuntimeException("非法参数");
        }
        if (BusServiceItem.SALESTATUS_ON.equals(busServiceItem.getSaleStatus())) {
            throw new RuntimeException("该服务项必须下架后才能删除");
        }
        if (BusServiceItem.CARPACKAGE_YES.equals(busServiceItem.getCarPackage()) && BusServiceItem.AUDITSTATUS_AUDITING.equals(busServiceItem.getAuditStatus())) {
            throw new RuntimeException("该套餐必须审核通过才能删除");
        }
        return busServiceItemMapper.deleteBusServiceById(id);
    }

    @Override
    //上架功能
    public int saleOn(Long id) {
        //参数合理化校验
        if (id == null) {
            throw new RuntimeException("非法参数");
        }
        BusServiceItem busServiceItem = this.selectBusServiceItemById(id);
        if (busServiceItem == null) {
            throw new RuntimeException("非法参数");
        }

        //必须是下架商品才能进行上架
        if (BusServiceItem.SALESTATUS_ON.equals(busServiceItem.getSaleStatus())) {
            throw new RuntimeException("该服务已上架");
        }

        //下架且非套餐可以直接上架
        //下架且是套餐 且状态是审核通过才能进行上架
        //是套餐 && 只要不是审核通过 ==》 不能上架
        if (BusServiceItem.CARPACKAGE_YES.equals(busServiceItem.getCarPackage()) && !BusServiceItem.AUDITSTATUS_APPROVED.equals(busServiceItem.getAuditStatus())) {
            throw new RuntimeException("该服务项必须审核通过后才能上架");
        }
        return busServiceItemMapper.changeSaleStatus(id, BusServiceItem.SALESTATUS_ON);
    }

    @Override
    //下架功能
    public int saleOff(Long id) {
        //参数合理化校验
        if (id == null) {
            throw new RuntimeException("非法参数");
        }
        BusServiceItem busServiceItem = this.selectBusServiceItemById(id);
        if (busServiceItem == null) {
            throw new RuntimeException("非法参数");
        }

        //必须是上架商品才能进行下架
        if (BusServiceItem.SALESTATUS_OFF.equals(busServiceItem.getSaleStatus())) {
            throw new RuntimeException("该服务已下架");
        }

        return busServiceItemMapper.changeSaleStatus(id, BusServiceItem.SALESTATUS_OFF);
    }

    @Override
    //查询审批页面数据
    public AuditInfoVO getAuditInfo(Long id) {
        //参数合法性验证
        if(id == null){
            throw new RuntimeException("非法参数");
        }
        BusServiceItem busServiceItem = this.selectBusServiceItemById(id);
        if(busServiceItem == null){
            throw new RuntimeException("非法参数");
        }
        //创建返回对象并封装数据
        AuditInfoVO vo = new AuditInfoVO();
        //准备服务项数据
        vo.setBusServiceItem(busServiceItem);
        //准备店长数据
        List<SysUser> userList =  sysUserService.selectUserByRoleKey("shopOwner");
        vo.setShopOwnerList(userList);
        //准备判定金额数据 从系统变量中获取的 以键值对形式存储
        String discountPriceLimit = sysConfigService.selectConfigByKey("discountPriceLimit");
        vo.setDiscountPriceLimit(new BigDecimal(discountPriceLimit));
        //传递的折扣必须>=3000才需要财务
        if(busServiceItem.getDiscountPrice().compareTo(new BigDecimal(discountPriceLimit)) >= 0){
            //准备财务数据
            List<SysUser> financeList =  sysUserService.selectUserByRoleKey("finance");
            vo.setFinanceList(financeList);
        }
        return vo;
    }

    /*发起审核功能*/
    @Override
    @Transactional
    public int startAudit(AuditVO vo) {
        if(vo == null){
            throw new RuntimeException("非法参数");
        }
        if(vo.getServiceItemId() == null || vo.getShopOwnerId() == null){
            throw new RuntimeException("非法参数");
        }

        //根据id查询服务项信息
        BusServiceItem busServiceItem = this.selectBusServiceItemById(vo.getServiceItemId());
        if(busServiceItem == null){
            throw new RuntimeException("非法参数");
        }
        //处于下架状态
        if(BusServiceItem.SALESTATUS_ON.equals(busServiceItem.getSaleStatus())){
            throw new RuntimeException("已上架的服务不能发起审批");
        }
        //非套餐禁止发起审批
        if(BusServiceItem.CARPACKAGE_NO.equals(busServiceItem.getCarPackage())){
            throw new RuntimeException("非套餐禁止发起审批");
        }
        //状态必须为初始化才能发起审批
        if(!(BusServiceItem.AUDITSTATUS_INIT.equals(busServiceItem.getAuditStatus()))){
            throw new RuntimeException("状态必须为初始化才能发起审批");
        }
        //封装需要插入的套餐审批记录  插入的是快照表
        BusCarPackageAudit busCarPackageAudit = new BusCarPackageAudit();
        busCarPackageAudit.setServiceItemId(busServiceItem.getId());
        busCarPackageAudit.setServiceItemName(busServiceItem.getName());
        busCarPackageAudit.setServiceItemInfo(busServiceItem.getInfo());
        busCarPackageAudit.setServiceItemPrice(busServiceItem.getDiscountPrice());
        busCarPackageAudit.setCreatorId(SecurityUtils.getUserId().toString());
        busCarPackageAudit.setInfo(busServiceItem.getInfo());
        //不用设置createTime 因为insertBusCarPackageAudit方法中已经设置了
        busCarPackageAudit.setStatus(BusCarPackageAudit.STATUS_IN_PROGRESS);
        //将封装好的数据插入到快照表中，这样插入后的对象就存在自增的id
        busCarPackageAuditService.insertBusCarPackageAudit(busCarPackageAudit);
        BusBpmnInfo busBpmnInfo = busBpmnInfoService.selectBusBpmnInfoByTypeId(BusCarPackageAudit.FLOW_AUDIT_TYPE);
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(busBpmnInfo.getProcessDefinitionKey()).processDefinitionVersion(busBpmnInfo.getVersion()).singleResult();
        String processDefinitionId = processDefinition.getId();
        //启动流程实例
        HashMap<String, Object> variables = new HashMap<>();
        variables.put("shopOwnerId",vo.getShopOwnerId());
        if(vo.getFinanceId() != null){
            variables.put("financeId",vo.getFinanceId());
        }
        //根据流程定义id,BusinessKey（业务Key）,流程变量（审批人）启动流程实例 快照表的id就是businessKey
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId, busCarPackageAudit.getId().toString(), variables);
        //有了流程实例对象，就可以获取到instanceId,再更新到快照表中
        busCarPackageAudit.setInstanceId(processInstance.getId());
        busCarPackageAuditService.updateInstanceIdById(busCarPackageAudit.getId(),processInstance.getId());

        //对审核记录进行更新
        return busServiceItemMapper.changeAuditStatus(vo.getServiceItemId(),BusServiceItem.AUDITSTATUS_AUDITING);

    }

    @Override
    public int changeStatusById(Long serviceItemId, Integer auditstatusInit) {
        return busServiceItemMapper.changeAuditStatus(serviceItemId,auditstatusInit);
    }
}
